/**
 * 
 */
package org.dragonfire.editor.z80;

import org.dragonfire.editor.syntax.rules.LineReturnRule;
import org.dragonfire.editor.syntax.rules.SingleCharRule;
import org.dragonfire.editor.z80.hiliteRules.CommandRule;
import org.dragonfire.editor.z80.hiliteRules.DirectiveRule;
import org.dragonfire.editor.z80.hiliteRules.FunctionRule;
import org.dragonfire.editor.z80.hiliteRules.LabelRule;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.jface.text.rules.EndOfLineRule;
import org.eclipse.jface.text.rules.IRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.IWhitespaceDetector;
import org.eclipse.jface.text.rules.RuleBasedScanner;
import org.eclipse.jface.text.rules.SingleLineRule;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.rules.WhitespaceRule;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;


/**
 * @author Darth Android
 * @date Oct 2, 2007
 */
public class AssemblyScanner extends RuleBasedScanner {

	public static final RGB STRING_COLOR = new RGB(255, 0, 0);
	public static final RGB COMMENT_COLOR = new RGB(255, 128, 0);
	public static final RGB DIRECTIVE_COLOR = new RGB(0, 0, 128);
	public static final RGB NUMBER_COLOR = new RGB(128, 0, 128);
	public static final RGB LABEL_COLOR = new RGB(0, 128, 0);
	public static final RGB PUNCTUATION_COLOR = new RGB(128, 128, 128);
	public static final RGB COMMAND_COLOR = new RGB(0, 128, 128);
	public static final RGB FUNCTION_COLOR = new RGB(0, 0, 255);

	private IRule lastRuleMatched = null;

	public AssemblyScanner() {

		Token stringToken = new Token(new TextAttribute(new Color(Display.getCurrent(), STRING_COLOR)));

		Token numberToken = new Token(new TextAttribute(new Color(Display.getCurrent(), NUMBER_COLOR)));

		// whitespace
		IWhitespaceDetector whitespaceRule = new IWhitespaceDetector() {

			public boolean isWhitespace(char c) {
				return Character.isWhitespace(c);
			}
		};
		IRule[] rules = new IRule[] {
				new LineReturnRule(), // line returns
				new EndOfLineRule(";", createToken(COMMENT_COLOR, SWT.ITALIC)), // comments
				new SingleLineRule("\"", "\"", stringToken, '\\'), // characters
				new SingleLineRule("'", "'", stringToken), // Strings
				new LabelRule(createToken(LABEL_COLOR)), // labels
				new DirectiveRule(), // directives
				new CommandRule(createToken(COMMAND_COLOR,SWT.BOLD)), // commands/macros
				new FunctionRule(createToken(FUNCTION_COLOR)), //function
				//new SimplePatternRule('$', "0123456789ABCDEFabcdef", 'h', numberToken, 1, -1), // hex
				//new SimplePatternRule('%', "01", 'b', numberToken, 1, -1), // binary
				//new SimplePatternRule('&', "01234567", 'o', numberToken, 1, -1), // octal
				//new ColumnWrapperRule(new NumberRule(numberToken), 1, -1), // decimal
				new SingleCharRule(createToken(PUNCTUATION_COLOR), "()-+*/^&|=><,"), // punctuation
				new WhitespaceRule(whitespaceRule)
		};
		setRules(rules);
	}

	public Token createToken(RGB color) {
		return new Token(new TextAttribute(new Color(Display.getCurrent(), color)));
	}

	public Token createToken(RGB color, int style) {
		return new Token(new TextAttribute(new Color(Display.getCurrent(), color), null, style));
	}

	public IToken nextToken() {

		fTokenOffset = fOffset;
		fColumn = UNDEFINED;

		if (fRules != null) {
			for (int i = 0; i < fRules.length; i++) {
				IToken token = (fRules[i].evaluate(this));
				if (!token.isUndefined()) {
					if (!(fRules[i] instanceof WhitespaceRule))
						lastRuleMatched = fRules[i];
					return token;
				}
			}
		}

		if (read() == EOF)
			return Token.EOF;
		return fDefaultReturnToken;
	}

	public IRule getLastMatchedRule() {
		return lastRuleMatched;
	}

}
